void POM_ComputeParams(
	float3 wView,
	
	float3 wNorm,
	float3 wTan,
	float3 wBin,
	
	float heightScale,
	
	out float3 oTsView,
	out float2 oPomDir
)
{
	float3x3 matWorldToTangent = float3x3( wTan, wBin, wNorm );
	float3 tsView = mul( matWorldToTangent, wView );

	tsView.z = abs( tsView.z );

	float pomLen = sqrt( dot( tsView, tsView ) - tsView.z * tsView.z ) / tsView.z;

	oTsView = tsView;
	oPomDir = normalize( tsView.xy ) * pomLen * heightScale;
}

float2 POM_Trace(
	sampler2D bumpTex,
	float2 bumpTexSize,
	
	float2 texCoord,
	
	float normDotView,
	float2 pomDir,
	
	int mipCutoff,
	int2 stepBounds
)
{	
	//compute mip levels and such
	float2 tcPerSize = texCoord * bumpTexSize;
	
	float2 dxSz, dx;
	float4( dxSz, dx ) = ddx( float4( tcPerSize, texCoord ) );
	
	float2 dySz, dy;
	float4( dySz, dy ) = ddy( float4( tcPerSize, texCoord ) );
	
	
	float2 texDelta = dxSz * dxSz + dySz * dySz;
	float mip = max( 0.5 * log2( max( texDelta.x, texDelta.y ) ), 0 );

	float2 tc = texCoord;

	if( mip <= mipCutoff )
	{	
		//POM		
		int steps = (int)lerp( stepBounds.y, stepBounds.x, saturate( normDotView ) );
		float stepSize = 1.0 / (float)steps;
		
		float2 tcOfsPerStep = stepSize * pomDir;
		
		float bound = 1;
				
		float prevHeight = 1;
		
		float2 p1 = 0;
		float2 p2 = 0;
		
		for( int step = 0; step < steps; step++ )
		{
			tc -= tcOfsPerStep;
			bound -= stepSize;
			
			float currHeight = tex2Dgrad( bumpTex, tc, dx, dy ).a;
		
			if( currHeight > bound )
			{
				p1 = float2( bound, currHeight );
				p2 = float2( bound + stepSize, prevHeight );
			
				step = steps;
			}
						
			prevHeight = currHeight;
		}
		
		float d1 = p1.x - p1.y;
		float d2 = p2.x - p2.y;
		
		float div = d2 - d1;
		float parallax = div == 0 ? 1 :
			1 - (p1.x * d2 - p2.x * d1) / div;
			
		tc = texCoord - pomDir * parallax;
		
		if( mip > (mipCutoff - 1) )
		{
			//transition back to regular texturing smoothly		
			tc = lerp( tc, texCoord, frac( mip ) );
		}
	}
	
	return tc;
}